/*******************************************************************************
** 文件名称：gm_lunar.c
** 文件作用：农历操作
** 创建作者：Tom Free 付瑞彪
** 创建时间：2021-01-07
**
**          Copyright (c) 2018-2021 付瑞彪 All Rights Reserved
**
**       1 Tab == 4 Spaces     UTF-8     ANSI C Language(C99)
*******************************************************************************/

#include "gm_lunar.h"
#include "gm_calendar.h"
#include "stdio.h"

/* 是否使能农历计算 */
#if (GM_CALENDAR_CFG_LUNAR_ENABLE > 0)

/* 定义农历计算的最小年份 */
#ifndef GM_CALENDAR_CFG_LUNAR_YEAR_MIN
#define GM_CALENDAR_CFG_LUNAR_YEAR_MIN  1901
#elif GM_CALENDAR_CFG_LUNAR_YEAR_MIN < 1901
#define GM_CALENDAR_CFG_LUNAR_YEAR_MIN  1901
#endif

/* 定义农历计算的最大年份 */
#ifndef GM_CALENDAR_CFG_LUNAR_YEAR_MAX
#define GM_CALENDAR_CFG_LUNAR_YEAR_MAX  2099
#elif GM_CALENDAR_CFG_LUNAR_YEAR_MAX > 2099
#define GM_CALENDAR_CFG_LUNAR_YEAR_MAX  2099
#endif

/* 判断年份设置是否正常 */
#if (GM_CALENDAR_CFG_LUNAR_YEAR_MAX < GM_CALENDAR_CFG_LUNAR_YEAR_MIN)
#error please set lunar year max no less than lunar year min
#endif

/* 是否包含当前年 */
#define GM_LUNAR_YEAR_INCLUDE(x)                    \
    ((GM_CALENDAR_CFG_LUNAR_YEAR_MAX >= (x)) &&     \
     (GM_CALENDAR_CFG_LUNAR_YEAR_MIN <= (x)))

/* 农历信息 */
typedef struct _lunar_info_t
{
    uint8_t cny_day;        /* 春节(Chinese New Year)对应的国际日历的日期 */
    uint8_t cny_month;      /* 春节(Chinese New Year)对应的国际日历的月份 */
    uint8_t days_list[13];  /* 每个月的日期列表 */
    uint8_t leap_month;     /* 农历闰月的月份 */
} lunar_info_t;

/**
 * 农历信息表，记录农历和国际日历的关系
 * [0..4]   共5bits  春节(正月初一)对应的国际日历的日期，例如12日
 * [5..6]   共2bits  春节(正月初一)对应的国际日历的月份，1或者2，例如2月
 * [7..19]  共13bits 13个月的大小月情况(如果无闰月，最后位无效)，
 *                   大月(30天)为1，小月(29天)为0
 * [20..23] 共4bits  记录农历闰月的月份，如果没有闰月为0
 */
static const uint32_t lunar_calendar_info_list[] =
{
#if GM_LUNAR_YEAR_INCLUDE(1901)
    0x04AE53,   /* 1901 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1902)
    0x0A5748,   /* 1902 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1903)
    0x5526BD,   /* 1903 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1904)
    0x0D2650,   /* 1904 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1905)
    0x0D9544,   /* 1905 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1906)
    0x46AAB9,   /* 1906 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1907)
    0x056A4D,   /* 1907 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1908)
    0x09AD42,   /* 1908 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1909)
    0x24AEB6,   /* 1909 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1910)
    0x04AE4A,   /* 1910 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1911)
    0x6A4DBE,   /* 1911 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1912)
    0x0A4D52,   /* 1912 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1913)
    0x0D2546,   /* 1913 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1914)
    0x5D52BA,   /* 1914 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1915)
    0x0B544E,   /* 1915 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1916)
    0x0D6A43,   /* 1916 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1917)
    0x296D37,   /* 1917 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1918)
    0x095B4B,   /* 1918 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1919)
    0x749BC1,   /* 1919 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1920)
    0x049754,   /* 1920 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1921)
    0x0A4B48,   /* 1921 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1922)
    0x5B25BC,   /* 1922 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1923)
    0x06A550,   /* 1923 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1924)
    0x06D445,   /* 1924 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1925)
    0x4ADAB8,   /* 1925 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1926)
    0x02B64D,   /* 1926 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1927)
    0x095742,   /* 1927 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1928)
    0x2497B7,   /* 1928 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1929)
    0x04974A,   /* 1929 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1930)
    0x664B3E,   /* 1930 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1931)
    0x0D4A51,   /* 1931 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1932)
    0x0EA546,   /* 1932 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1933)
    0x56D4BA,   /* 1933 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1934)
    0x05AD4E,   /* 1934 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1935)
    0x02B644,   /* 1935 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1936)
    0x393738,   /* 1936 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1937)
    0x092E4B,   /* 1937 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1938)
    0x7C96BF,   /* 1938 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1939)
    0x0C9553,   /* 1939 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1940)
    0x0D4A48,   /* 1940 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1941)
    0x6DA53B,   /* 1941 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1942)
    0x0B554F,   /* 1942 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1943)
    0x056A45,   /* 1943 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1944)
    0x4AADB9,   /* 1944 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1945)
    0x025D4D,   /* 1945 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1946)
    0x092D42,   /* 1946 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1947)
    0x2C95B6,   /* 1947 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1948)
    0x0A954A,   /* 1948 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1949)
    0x7B4ABD,   /* 1949 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1950)
    0x06CA51,   /* 1950 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1951)
    0x0B5546,   /* 1951 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1952)
    0x555ABB,   /* 1952 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1953)
    0x04DA4E,   /* 1953 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1954)
    0x0A5B43,   /* 1954 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1955)
    0x352BB8,   /* 1955 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1956)
    0x052B4C,   /* 1956 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1957)
    0x8A953F,   /* 1957 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1958)
    0x0E9552,   /* 1958 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1959)
    0x06AA48,   /* 1959 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1960)
    0x6AD53C,   /* 1960 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1961)
    0x0AB54F,   /* 1961 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1962)
    0x04B645,   /* 1962 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1963)
    0x4A5739,   /* 1963 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1964)
    0x0A574D,   /* 1964 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1965)
    0x052642,   /* 1965 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1966)
    0x3E9335,   /* 1966 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1967)
    0x0D9549,   /* 1967 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1968)
    0x75AABE,   /* 1968 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1969)
    0x056A51,   /* 1969 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1970)
    0x096D46,   /* 1970 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1971)
    0x54AEBB,   /* 1971 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1972)
    0x04AD4F,   /* 1972 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1973)
    0x0A4D43,   /* 1973 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1974)
    0x4D26B7,   /* 1974 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1975)
    0x0D254B,   /* 1975 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1976)
    0x8D52BF,   /* 1976 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1977)
    0x0B5452,   /* 1977 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1978)
    0x0B6A47,   /* 1978 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1979)
    0x696D3C,   /* 1979 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1980)
    0x095B50,   /* 1980 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1981)
    0x049B45,   /* 1981 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1982)
    0x4A4BB9,   /* 1982 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1983)
    0x0A4B4D,   /* 1983 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1984)
    0xAB25C2,   /* 1984 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1985)
    0x06A554,   /* 1985 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1986)
    0x06D449,   /* 1986 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1987)
    0x6ADA3D,   /* 1987 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1988)
    0x0AB651,   /* 1988 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1989)
    0x093746,   /* 1989 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1990)
    0x5497BB,   /* 1990 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1991)
    0x04974F,   /* 1991 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1992)
    0x064B44,   /* 1992 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1993)
    0x36A537,   /* 1993 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1994)
    0x0EA54A,   /* 1994 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1995)
    0x86B2BF,   /* 1995 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1996)
    0x05AC53,   /* 1996 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1997)
    0x0AB647,   /* 1997 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1998)
    0x5936BC,   /* 1998 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(1999)
    0x092E50,   /* 1999 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2000)
    0x0C9645,   /* 2000 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2001)
    0x4D4AB8,   /* 2001 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2002)
    0x0D4A4C,   /* 2002 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2003)
    0x0DA541,   /* 2003 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2004)
    0x25AAB6,   /* 2004 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2005)
    0x056A49,   /* 2005 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2006)
    0x7AADBD,   /* 2006 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2007)
    0x025D52,   /* 2007 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2008)
    0x092D47,   /* 2008 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2009)
    0x5C95BA,   /* 2009 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2010)
    0x0A954E,   /* 2010 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2011)
    0x0B4A43,   /* 2011 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2012)
    0x4B5537,   /* 2012 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2013)
    0x0AD54A,   /* 2013 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2014)
    0x955ABF,   /* 2014 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2015)
    0x04BA53,   /* 2015 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2016)
    0x0A5B48,   /* 2016 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2017)
    0x652BBC,   /* 2017 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2018)
    0x052B50,   /* 2018 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2019)
    0x0A9345,   /* 2019 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2020)
    0x474AB9,   /* 2020 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2021)
    0x06AA4C,   /* 2021 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2022)
    0x0AD541,   /* 2022 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2023)
    0x24DAB6,   /* 2023 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2024)
    0x04B64A,   /* 2024 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2025)
    0x69573D,   /* 2025 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2026)
    0x0A4E51,   /* 2026 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2027)
    0x0D2646,   /* 2027 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2028)
    0x5E933A,   /* 2028 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2029)
    0x0D534D,   /* 2029 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2030)
    0x05AA43,   /* 2030 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2031)
    0x36B537,   /* 2031 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2032)
    0x096D4B,   /* 2032 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2033)
    0xB4AEBF,   /* 2033 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2034)
    0x04AD53,   /* 2034 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2035)
    0x0A4D48,   /* 2035 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2036)
    0x6D25BC,   /* 2036 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2037)
    0x0D254F,   /* 2037 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2038)
    0x0D5244,   /* 2038 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2039)
    0x5DAA38,   /* 2039 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2040)
    0x0B5A4C,   /* 2040 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2041)
    0x056D41,   /* 2041 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2042)
    0x24ADB6,   /* 2042 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2043)
    0x049B4A,   /* 2043 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2044)
    0x7A4BBE,   /* 2044 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2045)
    0x0A4B51,   /* 2045 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2046)
    0x0AA546,   /* 2046 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2047)
    0x5B52BA,   /* 2047 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2048)
    0x06D24E,   /* 2048 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2049)
    0x0ADA42,   /* 2049 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2050)
    0x355B37,   /* 2050 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2051)
    0x09374B,   /* 2051 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2052)
    0x8497C1,   /* 2052 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2053)
    0x049753,   /* 2053 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2054)
    0x064B48,   /* 2054 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2055)
    0x66A53C,   /* 2055 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2056)
    0x0EA54F,   /* 2056 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2057)
    0x06B244,   /* 2057 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2058)
    0x4AB638,   /* 2058 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2059)
    0x0AAE4C,   /* 2059 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2060)
    0x092E42,   /* 2060 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2061)
    0x3C9735,   /* 2061 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2062)
    0x0C9649,   /* 2062 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2063)
    0x7D4ABD,   /* 2063 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2064)
    0x0D4A51,   /* 2064 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2065)
    0x0DA545,   /* 2065 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2066)
    0x55AABA,   /* 2066 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2067)
    0x056A4E,   /* 2067 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2068)
    0x0A6D43,   /* 2068 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2069)
    0x452EB7,   /* 2069 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2070)
    0x052D4B,   /* 2070 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2071)
    0x8A95BF,   /* 2071 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2072)
    0x0A9553,   /* 2072 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2073)
    0x0B4A47,   /* 2073 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2074)
    0x6B553B,   /* 2074 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2075)
    0x0AD54F,   /* 2075 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2076)
    0x055A45,   /* 2076 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2077)
    0x4A5D38,   /* 2077 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2078)
    0x0A5B4C,   /* 2078 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2079)
    0x052B42,   /* 2079 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2080)
    0x3A93B6,   /* 2080 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2081)
    0x069349,   /* 2081 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2082)
    0x7729BD,   /* 2082 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2083)
    0x06AA51,   /* 2083 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2084)
    0x0AD546,   /* 2084 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2085)
    0x54DABA,   /* 2085 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2086)
    0x04B64E,   /* 2086 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2087)
    0x0A5743,   /* 2087 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2088)
    0x452738,   /* 2088 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2089)
    0x0D264A,   /* 2089 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2090)
    0x8E933E,   /* 2090 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2091)
    0x0D5252,   /* 2091 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2092)
    0x0DAA47,   /* 2092 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2093)
    0x66B53B,   /* 2093 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2094)
    0x056D4F,   /* 2094 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2095)
    0x04AE45,   /* 2095 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2096)
    0x4A4EB9,   /* 2096 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2097)
    0x0A4D4C,   /* 2097 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2098)
    0x0D1541,   /* 2098 */
#endif
#if GM_LUNAR_YEAR_INCLUDE(2099)
    0x2D92B5,   /* 2099 */
#endif
};

/* 获取农历信息，保证年在可计算范围内且p_info不为NULL，内部没有判断 */
static void gm_lunar_get_info(uint16_t year, lunar_info_t *p_info)
{
    uint32_t info_data;

    info_data = lunar_calendar_info_list[year - GM_CALENDAR_CFG_LUNAR_YEAR_MIN];
    /* 5位日期 */
    p_info->cny_day = info_data & 0x1F;
    info_data >>= 5;
    /* 2位月份 */
    p_info->cny_month = info_data & 0x03;
    info_data >>= 2;
    /* 13位日期 */
    for (int i = 0; i < 13; i++)
    {
        if (info_data & 0x01)
        {
            p_info->days_list[12 - i] = 30;
        }
        else
        {
            p_info->days_list[12 - i] = 29;
        }
        info_data >>= 1;
    }
    /* 4位闰月 */
    p_info->leap_month = info_data & 0x0F;
}

/* 今年是否是闰年，保证年在可计算范围内，内部没有判断 */
static uint8_t gm_lunar_get_leap_month(uint16_t year)
{
    uint32_t info_data;

    info_data = lunar_calendar_info_list[year - GM_CALENDAR_CFG_LUNAR_YEAR_MIN];

    /* 4位闰月 */
    return ((info_data >> 20) & 0x0F);
}

/* 月份转信息索引值，保证年和月在可计算范围内 */
static uint8_t gm_lunar_month_to_info_index(uint16_t year, uint8_t month, bool is_leap)
{
    uint8_t leap_month = gm_lunar_get_leap_month(year);

    if (leap_month > 0)
    {
        /* 此年有闰月 */
        if ((month > leap_month) || (is_leap == true))
        {
            /* 大于闰月或者此月是闰月 */
            return month;
        }
        else
        {
            /* 小于或等于此月且此月不是闰月 */
            return month - 1;
        }
    }
    else
    {
        /* 此年无闰月，返回月 */
        return month - 1;
    }
}

/* 获取当前月的总天数 */
uint8_t gm_lunar_get_month_days(const gm_lunar_t * const p_lunar)
{
    uint8_t  index;
    uint8_t  leap_month;
    uint32_t info_data;

    if ((p_lunar == NULL) ||
        (p_lunar->year < GM_CALENDAR_CFG_LUNAR_YEAR_MIN) ||
        (p_lunar->year > GM_CALENDAR_CFG_LUNAR_YEAR_MAX) ||
        (p_lunar->month < 1) ||
        (p_lunar->month > 12))
    {
        /* 年月参数错误 */
        return 0;
    }

    leap_month = gm_lunar_get_leap_month(p_lunar->year);
    if ((p_lunar->is_leap == true) && (leap_month != p_lunar->month))
    {
        /* 此月不是闰月，但输入参数却是，返回失败 */
        return 0;
    }

    index = gm_lunar_month_to_info_index(p_lunar->year, p_lunar->month, p_lunar->is_leap);
    info_data = lunar_calendar_info_list[p_lunar->year - GM_CALENDAR_CFG_LUNAR_YEAR_MIN];

    return ((info_data & (0x80000 >> index)) ? 30 : 29);
}

/* 计算当前日期在今年的总天数 */
uint16_t gm_lunar_calc_now_days(const gm_lunar_t * const p_lunar)
{
    uint8_t      index;
    uint8_t      leap_month;
    uint16_t     days;
    lunar_info_t lunar_info;

    if ((p_lunar == NULL) ||
        (p_lunar->year < GM_CALENDAR_CFG_LUNAR_YEAR_MIN) ||
        (p_lunar->year > GM_CALENDAR_CFG_LUNAR_YEAR_MAX) ||
        (p_lunar->month < 1) ||
        (p_lunar->month > 12))
    {
        /* 年月参数错误 */
        return 0;
    }

    leap_month = gm_lunar_get_leap_month(p_lunar->year);
    if ((p_lunar->is_leap == true) && (leap_month != p_lunar->month))
    {
        /* 此月不是闰月，但输入参数却是，返回失败 */
        return 0;
    }

    /* 计算当前索引号 */
    index = gm_lunar_month_to_info_index(p_lunar->year, p_lunar->month, p_lunar->is_leap);
    /* 获取信息 */
    gm_lunar_get_info(p_lunar->year, &lunar_info);

    days = 0;
    for (uint8_t i = 0; i < index; i++)
    {
        days += lunar_info.days_list[i];
    }
    days += p_lunar->day;

    return days;
}

/* 判断农历日期是否合法 */
bool gm_lunar_check_date_validity(const gm_lunar_t * const p_lunar)
{
    /* 此函数内部有年月和闰月判断 */
    uint8_t month_days = gm_lunar_get_month_days(p_lunar);

    /* 只需要判断函数是否成功和日的范围即可 */
    if ((month_days == 0) ||
        (p_lunar->day < 1) ||
        (p_lunar->day > month_days))
    {
        return false;
    }

    return true;
}

/* 日历到农历转换，输入日历的日期，转换为农历日期 */
bool gm_calendar_solar_to_lunar(const gm_solar_t * const p_solar, gm_lunar_t * const p_lunar)
{
    uint16_t     days, cny_days;
    lunar_info_t lunar_info;
    uint8_t      index, flag; 

    /* 时间有效性判断 */
    if ((p_lunar == NULL) || (p_lunar == NULL) ||
        (p_solar->year < (GM_CALENDAR_CFG_LUNAR_YEAR_MIN)) ||
        (p_solar->year > (GM_CALENDAR_CFG_LUNAR_YEAR_MAX)) ||
        (p_solar->month == 0) ||
        (p_solar->month > 12) ||
        (p_solar->day == 0) ||
        (p_solar->day > gm_calendar_get_month_days(p_solar->year, p_solar->month)) ||
        (p_lunar == NULL))
    {
        return false;
    }

    /* 获取信息 */
    gm_lunar_get_info(p_solar->year, &lunar_info);
    /* 计算当前日历相对于元旦的天数 */
    days = gm_calendar_calc_now_days(p_solar->year, p_solar->month, p_solar->day);

    /* 春节相对于元旦的天数 */
    if (lunar_info.cny_month == 1)
    {
        cny_days = lunar_info.cny_day;
    }
    else
    {
        cny_days = lunar_info.cny_day + 31;
    }
    p_lunar->is_leap = false;
    if (days >= cny_days)
    {
        p_lunar->year = p_solar->year;
        days -= cny_days;
        index = 0;
        flag = 0;
        p_lunar->month = 1;
        while (days >= lunar_info.days_list[index])
        {
            days -= lunar_info.days_list[index];
            index++;
            if (lunar_info.leap_month == p_lunar->month)
            {
                flag = ~flag;
                if (flag != 0)
                {
                    /* 下月为闰月 */
                    p_lunar->is_leap = true;
                    /* 下月是闰月，所以月份不能增加 */
                    continue;
                }
                else
                {
                    /* 下月为正常月，后面月份需要增加 */
                    p_lunar->is_leap = false;
                }
            }
            else
            {
                /* 下月为正常月 */
                p_lunar->is_leap = false;
            }
            p_lunar->month++;
        }
        p_lunar->day = days + 1;
    }
    else
    {
        if ((p_solar->year - 1) < (GM_CALENDAR_CFG_LUNAR_YEAR_MIN))
        {
            /* 之前的年没有信息，退出 */
            return false;
        }
        gm_lunar_get_info(p_solar->year - 1, &lunar_info);
        p_lunar->year = p_solar->year - 1;
        days = cny_days - days;
        if (lunar_info.leap_month)
        {
            index = 12;
        }
        else
        {
            index = 11;
        }
        flag = 0;
        p_lunar->month = 12;
        while (days >= lunar_info.days_list[index])
        {
            days -= lunar_info.days_list[index];
            index--;

            if (flag == 0)
            {
                /* 下月为正常月，后面月份需要减少 */
                p_lunar->is_leap = false;
                p_lunar->month--;
            }
            if (lunar_info.leap_month == p_lunar->month)
            {
                flag = ~flag;
                if (flag != 0)
                {
                    /* 下月为闰月 */
                    p_lunar->is_leap = true;
                    /* 下月是闰月，所以月份不能增加 */
                    continue;
                }
            }
            else
            {
                /* 下月为正常月 */
                p_lunar->is_leap = false;
            }
        }
        p_lunar->day = lunar_info.days_list[index] - days + 1;
    }

    return true;
}

/* 农历到日历转换，输入农历的日期，转换为日历日期 */
bool gm_calendar_lunar_to_solar(const gm_lunar_t * const p_lunar, gm_solar_t * const p_solar)
{
    gm_lunar_t   lunar = *p_lunar;
    lunar_info_t lunar_info;
    uint16_t     days, cny_days;
    uint8_t      month_days;

    /* 判断参数合法性 */
    if ((p_lunar == NULL) ||
        (p_solar == NULL) ||
        (gm_lunar_check_date_validity(&lunar) != true))
    {
        return false;
    }

    /* 获取信息 */
    gm_lunar_get_info(lunar.year, &lunar_info);
    /* 春节相对于元旦的天数 */
    if (lunar_info.cny_month == 1)
    {
        cny_days = lunar_info.cny_day;
    }
    else
    {
        cny_days = lunar_info.cny_day + 31;
    }
    /* 天数先加上春节的，因为日期肯定在春节之后 */
    days = cny_days - 1;
    /* 加上当前的天数 */
    days += gm_lunar_calc_now_days(&lunar);

    p_solar->year = lunar.year;
    p_solar->month = 1;
    p_solar->day = 1;
    month_days = gm_calendar_get_month_days(p_solar->year, p_solar->month);
    while (days > month_days)
    {
        days -= month_days;
        if (p_solar->month < 12)
        {
            p_solar->month++;
        }
        else
        {
            p_solar->month = 1;
            p_solar->year++;
        }
        month_days = gm_calendar_get_month_days(p_solar->year, p_solar->month);
    }
    p_solar->day = days;

    return true;
}

#endif  /* GM_CALENDAR_CFG_LUNAR_ENABLE > 0 */
